﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

namespace AccessControl
{
    /// <summary>
    /// 过期锁定模块
    /// </summary>
    public class AccessControler
    {
        public AccessControler(DateTime finTime)
        {
            thread = new Thread(ACComparer)
            {
                IsBackground = true
            };
            FinTime = finTime;
            ReadLastReadTime();
        }

        /// <summary>
        /// 过期锁定时间
        /// </summary>
        public DateTime FinTime { get; set; }

        /// <summary>
        /// 上次读取的时间
        /// </summary>
        public DateTime LastReadTime { get; set; }

        /// <summary>
        /// 程序过期事件
        /// </summary>
        public event EventHandler<ACEventArgs> AccessTimeOut;

        private void OnAccessTimeOut(string info)
        {
            ACEventArgs args = new ACEventArgs(info);

            // 以线程安全的方式引发事件
            var temp = Volatile.Read(ref AccessTimeOut);
            temp?.Invoke(this, args);
        }

        #region 工作线程

        private readonly Thread thread;
        private bool running = true;
        /// <summary>
        /// 比较设定时间和当前时间的线程方法
        /// 10分钟判断一次
        /// </summary>
        private void ACComparer()
        {
            DateTime ReadNow;
            while (running)
            {
                try
                {
                    ReadNow = DateTime.Now;
                    if (HasFlagFile())
                    {
                        // 过期
                        OnAccessTimeOut("程序已过期，请联系支持人员。");
                    }
                    else if (ReadNow > FinTime)
                    {
                        // 过期锁定
                        OnAccessTimeOut("程序已过期，请联系支持人员。");
                        CreateFlagFile();
                    }
                    else if (ReadNow < LastReadTime)
                    {
                        // 时间异常
                        OnAccessTimeOut("时间异常调整,请不要手动调整系统时间。");
                    }

                    // 记录运行时间
                    LastReadTime = ReadNow;
                    SaveLastReadTime();
                }
                catch 
                {
                }

                Thread.Sleep(new TimeSpan(0, 10, 0));
            }
        }

        /// <summary>
        /// 启动比较线程
        /// </summary>
        public void StartCompare()
        {
            running = true;
            // 如果线程已启动就直接返回
            if (thread.ThreadState == System.Threading.ThreadState.Running)
                return;
            // 如果线程未启动或者线程已停止就直接启动
            else if ((thread.ThreadState & (System.Threading.ThreadState.Unstarted | System.Threading.ThreadState.Stopped)) != 0)
            {
                thread.Start();
            }
            // 其他情况，强制终止然后启动
            else
            {
                thread.Abort();
                thread.Start();
            }

        }

        /// <summary>
        /// 结束比较线程  （10分钟内线程才会结束）
        /// </summary>
        public void StopCompare()
        {
            running = false;
        }

        #endregion

        #region 运行时间的记录和读取
        private readonly string LastDateTimePath = @"C:\trcTimer.ini";
        /// <summary>
        /// 保存上次读取的时间
        /// </summary>
        private void SaveLastReadTime()
        {
            try
            {
                using (StreamWriter sw = new StreamWriter(LastDateTimePath, false, Encoding.UTF8))
                {
                    sw.WriteLine(LastReadTime.ToString("yyyy/MM/dd"));
                }
                File.SetAttributes(LastDateTimePath, FileAttributes.System | FileAttributes.Hidden);
            }
            catch 
            {
                
            }

        }
        /// <summary>
        /// 读取上次保存的时间
        /// </summary>
        private void ReadLastReadTime()
        {
            try
            {
                if (File.Exists(LastDateTimePath))
                {
                    using (StreamReader sr = new StreamReader(LastDateTimePath, Encoding.UTF8))
                    {
                        DateTime.TryParse(sr.ReadLine(), out DateTime lastTime);
                        LastReadTime = lastTime;
                    }
                }
                else
                {
                    LastReadTime = DateTime.MinValue;
                }
            }
            catch 
            {
                
            }
        }
        #endregion

        #region 锁定标志
        private readonly string FlagPath = @"C:\trcLocker";

        public void CreateFlagFile()
        {
            File.Create(FlagPath);
            File.SetAttributes(FlagPath, FileAttributes.System | FileAttributes.Hidden);
        }

        public bool HasFlagFile()
        {
            return File.Exists(FlagPath);
        }
        #endregion
    }


}
